from datetime import datetime, timedelta

from accounts.models import Friendship
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.views.generic import ListView

from .forms import BookmarkForm
from .models import Bookmark, Link, Tag, Like

User = get_user_model()

MAX_WEIGHT = 5


class BookmarkListView(ListView):
    """首页"""
    template_name = 'bookmarks/bookmark_list.html'
    context_object_name = 'bookmarks'

    def get_queryset(self):
        return Bookmark.objects.all().select_related('user').select_related('link').prefetch_related('tag_set')


def user_bookmarks(request, username):
    """用户书签页面"""
    user = get_object_or_404(User, username=username)
    bookmarks = user.bookmark_set.all()

    is_friend = Friendship.objects.filter(from_friend=request.user, to_friend=user)
    context = {
        'username': username,
        'bookmarks': bookmarks,
        'is_friend': is_friend,
    }
    return render(request, 'bookmarks/user_bookmarks.html', context)


@login_required
def new_bookmark(request):
    """创建书签视图"""
    form = BookmarkForm()
    if request.method == 'POST':
        form = BookmarkForm(request.POST)
        if form.is_valid():
            link, _ = Link.objects.get_or_create(url=form.cleaned_data['url'])

            # 根据用户和链接获取或者创建
            bookmark, created = Bookmark.objects.get_or_create(
                user=request.user,
                link=link
            )

            # 更新标题
            bookmark.title = form.cleaned_data['title']

            # 如果存在同一个用户的用一个链接，清除掉所有的标签
            if not created:
                bookmark.tag_set.clear()

            # 重新添加标签
            tag_names = form.cleaned_data['tags'].strip().split()  # ['Django', 'Python', 'Java']
            for tag_name in tag_names:
                tag, _ = Tag.objects.get_or_create(name=tag_name)
                bookmark.tag_set.add(tag)

            bookmark.save()
            return redirect(reverse('bookmark_list'))

    context = {'form': form}
    return render(request, 'bookmarks/bookmark_form.html', context=context)


def tag_bookmarks(request, tag_name):
    """标签下的书签页面"""
    tag = get_object_or_404(Tag, name=tag_name)
    bookmarks = tag.bookmarks.all().order_by('-date_created')
    context = {'bookmarks': bookmarks, 'tag_name': tag_name}
    return render(request, 'bookmarks/tag_bookmarks.html', context)


def tag_cloud(request):
    """书签云
    获取每个标签的权重，0到5之间
    一个标签在不同书签中出现的次数越多权重越大
    """
    tags = Tag.objects.order_by('name')

    # 获取标签出现的最大次数和最小次数
    min_count = max_count = tags[0].bookmarks.count()
    for tag in tags:
        tag.count = tag.bookmarks.count()
        if tag.count < min_count:
            min_count = tag.count
        if tag.count > max_count:
            max_count = tag.count

    # 计算权重
    count_range = float(max_count - min_count)
    if count_range == 0.0:  # 避免除零错误
        count_range = 1.0
    for tag in tags:
        tag.weight = int(MAX_WEIGHT * (tag.count - min_count) / count_range)
    context = {'tags': tags}
    return render(request, 'bookmarks/tag_cloud.html', context)


@login_required
def bookmark_like(request, pk):
    """书签点赞"""
    bookmark = get_object_or_404(Bookmark, id=pk)
    _, created = Like.objects.get_or_create(
        user=request.user,
        bookmark=bookmark
    )
    if created:
        bookmark.num_likes += 1
        bookmark.save()
    else:
        messages.warning(request, '你已经点赞过！')
    return redirect(reverse('bookmark_list'))


def popular_bookmarks(request):
    """热门书签
    根据点赞数得到一天内的10条热门书签
    """
    today = datetime.today()
    yesterday = today - timedelta(days=1)
    bookmarks = Bookmark.objects.filter(date_created__gt=yesterday)
    bookmarks = bookmarks.order_by('-num_likes', '-date_created')[:10]
    context = {'bookmarks': bookmarks}
    return render(request, 'bookmarks/popular_bookmarks.html', context=context)
